package thread;

/**
 * 静态方法锁
 * 当我们在静态方法上加锁时，那么该方法
 */
public class SyncDemo3 {
    public static void main(String[] args) {

        //如果我们在静态方法上加锁，那边的锁是类对象，两个实例对象看到的是同一个静态方法，因此不能同时执行

        Foo f1=new Foo();
        Foo f2=new Foo();
        new Thread(()->f1.doSome()).start();
        new Thread(()->f2.doSome()).start();


        /*new Thread(Foo::doSome).start();
        new Thread(Foo::doSome).start();*/
    }
}

class Foo{
    /*
        如果doSome方法是成员方法:
        public synchronized void doSome(){..}   那么此时synchronized指定的同步监视器对象为this
        因此如果两个线程调用时:
        new Thread(()->f1.doSome()).start();    该线程看到的同步监视器为f1
        new Thread(()->f2.doSome()).start();    该线程看到的同步监视器为f2
        由于两个线程看到的并非同一个对象,因此两个线程互不影响，可以一起执行

        如果doSome方法是静态方法:
        public static synchronized void doSome(){..}
        那么此时synchronized指定的同步监视器对象为Foo.class  注:每个类仅有一个类对象(后面反射知识会讲)
        因此如果两个线程调用时:
        new Thread(()->f1.doSome()).start();
        new Thread(()->f2.doSome()).start();
        由于两个线程看到的同步监视器对象是同一个对象,因此两个线程互斥，只能一个线程执行
     */
    public static synchronized void doSome(){
        //在静态方法中使用静态块
        synchronized (Foo.class) {//静态方法的同步块中指定同步监视器对象依然是类对象
            try {
                Thread t = Thread.currentThread();
                System.out.println(t.getName() + "正在执行doSome方法");
                Thread.sleep(5000);
                System.out.println(t.getName() + "结束");
            } catch (InterruptedException e) {

            }
        }


    }
}

